/*
 * my_cli_pro.c
 *
 *  Created on: Aug 31, 2009
 *      Author: lius
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "my_plugin.h"
#include "my_debug.h"

epoll_cntl_func my_cli_cntl;
epoll_recv_func my_cli_recv;
epoll_send_func my_cli_send;
void *pbase = NULL;

const int mail_count = 33;

char mail_data_buf[65535] = {};
int mail_len = 0;

typedef struct _link_info{
	int offset;
	int status;
	int mail_count;
} link_info_t;

link_info_t link_info[65535] = {};

#define INDEX(handle) ((handle / 10000)*10000 + (handle % 10000))

enum {
	POP_CONNECT = -1,
	POP_SERVER_BANNER = 0,
	POP_SERVER_USER,
	POP_SERVER_PASS,
	POP_SERVER_LIST,
	POP_SERVER_UIDL,
	POP_SERVER_STAT,
	POP_SERVER_RETR,
	POP_SERVER_QUIT
};

char globle_data_buf[][255] = { "",
								"user lius\r\n",
								"pass neteye\r\n",
								"list\r\n",
								"uidl\r\n",
								"stat\r\n",
								"retr",
								"quit\r\n"
								};

inline void pop_stat_turn(link_info_t *pinfo, int cli_stat, int offset)
{
	//printf("pinfo->mail_count=[%d]\n", pinfo->mail_count);
	if(cli_stat == POP_SERVER_RETR)
	{
		if(--pinfo->mail_count == 0)
		{
			DEBUG_EPOLL(EPOLL_DBG_STAT, EPOLL_DEBUG, "before status=[%d];offset=[%d]\n", pinfo->status, pinfo->offset);
			pinfo->status = cli_stat + 1 > POP_SERVER_QUIT ? POP_SERVER_USER : cli_stat + 1;
			pinfo->offset = offset;
			DEBUG_EPOLL(EPOLL_DBG_STAT, EPOLL_DEBUG, "now    status=[%d];offset=[%d]\n", pinfo->status, pinfo->offset);
		}
	}
	else
	{
		DEBUG_EPOLL(EPOLL_DBG_STAT, EPOLL_DEBUG, "before status=[%d];offset=[%d]\n", pinfo->status, pinfo->offset);
		pinfo->status = cli_stat + 1 > POP_SERVER_QUIT ? POP_SERVER_USER : cli_stat + 1;
		pinfo->offset = offset;
		DEBUG_EPOLL(EPOLL_DBG_STAT, EPOLL_DEBUG, "now    status=[%d];offset=[%d]\n", pinfo->status, pinfo->offset);
	}
}

inline int my_rand_int(int max)
{
	int ret = rand() % max + 1;
	return ret;
}


int my_cli_init(base_func_t *pfunc)
{
	FUNC_START("pfunc = [%p]\n", pfunc);
	my_cli_cntl = pfunc->epoll_cntl;
	my_cli_recv = pfunc->epoll_recv;
	my_cli_send = pfunc->epoll_send;
	pbase = pfunc->pepoll;
	srand(time(NULL));
	FUNC_RETURN(0);
}

int my_cli_exit(void)
{
	FUNC_START("\n");
	FUNC_RETURN(0);
}


int my_cli_start(int handle)
{
	FUNC_START("handle = [%d]\n", handle);
	link_info_t *pinfo = &link_info[INDEX(handle)];
	pinfo->offset = 0;
	pinfo->status = POP_CONNECT;
	pinfo->mail_count = mail_count;
	FUNC_RETURN(0);
}


int my_cli_write(int handle)
{
	char *data_buf = NULL;
	char tmp[256];
	int  buf_len = 0;
	int ret = 0;
	int send_len = 0;
	link_info_t *pinfo = &link_info[INDEX(handle)];

	FUNC_START("handle = [%d]\n", handle);
	DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_DEBUG, "cli status=[%d]\n", pinfo->status);
	DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_DEBUG, "send data offset=[%d]\n", pinfo->offset);
	if(pinfo->status == POP_SERVER_BANNER)
	{
		my_cli_cntl(pbase, handle, EPOLL_OP_MODIFY, EPOLL_EV_READ);
		FUNC_RETURN(1);
	}
	if(pinfo->status == POP_CONNECT)
	{
		pop_stat_turn(pinfo, pinfo->status, 0);
		my_cli_cntl(pbase, handle, EPOLL_OP_MODIFY, EPOLL_EV_READ);
		FUNC_RETURN(1);
	}

	if(pinfo->status == POP_SERVER_RETR)
	{
		buf_len = send_len = sprintf(tmp, "%s %d\r\n", (char *)globle_data_buf[pinfo->status] + pinfo->offset, my_rand_int(150));
		data_buf = tmp;
	}
	else
	{
		data_buf = (char *)globle_data_buf[pinfo->status] + pinfo->offset;
		buf_len = send_len = strlen(data_buf);
	}

	//printf("data_buf=[%s]buf_len=[%d]\n", data_buf,buf_len);
	DEBUG_EPOLL(EPOLL_DBG_DATA, EPOLL_DEBUG, "before send data=[%.*s]\n", send_len, data_buf);
	ret = my_cli_send(handle, data_buf, send_len);
	DEBUG_EPOLL(EPOLL_DBG_FUNC, EPOLL_DEBUG, "before send ret=[%d]\n", ret);
	if(ret <= 0)
	{
		//my_cli_cntl(pbase, handle, EPOLL_OP_CLOSE, EPOLL_EV_RANDW);
		//FUNC_RETURN(-1);
	}
	else
	{
		my_cli_cntl(pbase, handle, EPOLL_OP_MODIFY, EPOLL_EV_READ);
	}

	FUNC_RETURN(ret);
}

int my_cli_read(int handle)
{
	char data_buf[65535];
	int ret = 0;
	link_info_t *pinfo = &link_info[INDEX(handle)];

	FUNC_START("handle = [%d]\n", handle);

	memset(data_buf, 0x00, sizeof(data_buf));
	ret = my_cli_recv(handle, data_buf, sizeof(data_buf) - 1);
	DEBUG_EPOLL(EPOLL_DBG_DATA, EPOLL_DEBUG, "recv data=[%.*s]\n", ret, data_buf);
	if(ret > 0)
	{
		if(pinfo->status == POP_SERVER_RETR ||
			pinfo->status == POP_SERVER_LIST ||
			pinfo->status == POP_SERVER_UIDL)
		{
			if(data_buf[ret - 5] == '\r' && data_buf[ret - 4] == '\n' &&
					data_buf[ret - 3] == '.' &&
					data_buf[ret - 2] == '\r' && data_buf[ret - 1] == '\n')
			{
				pop_stat_turn(pinfo, pinfo->status, 0);
				my_cli_write(handle);
			}
		}
		else if(pinfo->status != POP_SERVER_QUIT)
		{
			if(data_buf[ret - 2] == '\r' && data_buf[ret - 1] == '\n')
			{
				if(pinfo->status == POP_CONNECT)
				{
					pop_stat_turn(pinfo, pinfo->status + 1, 0);
				}
				else
				{
					pop_stat_turn(pinfo, pinfo->status, 0);
					my_cli_write(handle);
				}

			}
		}

	//	FUNC_RETURN(ret);
	}
	//else
	//{
	//	my_cli_cntl(pbase, handle, EPOLL_OP_CLOSE, EPOLL_EV_RANDW);
		FUNC_RETURN(ret);
	//}
}

int my_cli_end(int handle)
{
	FUNC_START("handle = [%d]\n", handle);
	my_cli_cntl(pbase, handle, EPOLL_OP_CLOSE, EPOLL_EV_RANDW);
	FUNC_RETURN(0);
}

